import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.util.ArrayList;

public class Interpreter {
	private Token[] tokens;
	private ArrayList<ArrayList<String>> finds = new ArrayList<ArrayList<String>>();
	private ArrayList<ArrayList<String>> replaces = new ArrayList<ArrayList<String>>();
	private DFA regexDFA;
	public Interpreter(Token[] tokens) {
		this.tokens = tokens;
		/**
		try {
			regexDFA = ScannerGenerator.dfaFromLexicalSpec("regexSpec.txt");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Failed to load Regex Spec File.");
			e.printStackTrace();
		}*/
	}

	/**
	 * Kaitlin
	 */
	public boolean MiniREProgram() {
		int index = 0;
		boolean state;
		if (tokens[index].getString().equals("begin")) {
			index++;
		}// end if statement
		else {
			return false;
		}
		state = statementList(index);
		if(!state)
		{
			return false;
		}
		if (tokens[index].getString().equals("end")) {
			index++;
		}// end if statement
		else {
			return false;
		}
		return true;
	}// end MiniReProgram method

	/**
	 * Leah
	 */
	public boolean statementList(int index) {
		boolean state;
		state = statement(index);
		if (!state) {
			return false;
		}
		state = statementListTail(index);
		return state;
	}// end statementList method

	/**
	 * Kaitlin
	 */
	public boolean statement(int index) {
		boolean state;
		if(tokens[index].getType().equals("ID"))
		{
			index++;
			if (tokens[index].getString().equals("=")) {
				index++;
				if (tokens[index].getString().equals("maxfreqstring")) {
					index++;
					if (tokens[index].getString().equals("(")) {
						index++;
					}// end if statement
					else {
						return false;
					}
					if(tokens[index].getType().equals("ID"))
					{
						index++;
					}// end if statement
					else {
						return false;
					}
					if (tokens[index].getString().equals(")")) {
						index++;
					}// end if statement
					else {
						return false;
					}
					if (tokens[index].getString().equals(";")) {
						index++;
					}// end if statement
					else {
						return false;
					}
				}// end if statement
				else if (tokens[index].getString().equals("#")) {
					state = exp(index);
					if (!state) {
						return false;
					}
					if (tokens[index].getString().equals(";")) {
						index++;
					}// end if statement
					else {
						return false;
					}
				}//end else if statement
				else if(tokens[index].getString().equals("ID")||tokens[index].getString().equals("(")||tokens[index].getString().equals("find"))
				{
					state = exp(index);
					if (!state) {
						return false;
					}
					if (tokens[index].getString().equals(";")) {
						index++;
					}// end if statement
					else {
						return false;
					}// end else statement
				}// end else if statement
			} else {
				return false;
			}// end else statement
		}// end if statement
		else if (tokens[index].getString().equals("recursivereplace")) {
			index++;
			if(tokens[index].getType().equals("REGEX"))
			{
				index++;
			}// end if statement
			else {
				return false;
			}
			if (tokens[index].getString().equals("with")) {
				index++;
			}// end if statement
			else {
				return false;
			}//end else statement
			if(tokens[index].getString().equals("ASCII-STR"))
			{
				index++;
			}// end if statement
			else {
				return false;
			}
			if (tokens[index].getString().equals("in")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
			state = fileNames(index);
			if (!state) {
				return false;
			}
			if (tokens[index].getString().equals(";")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
		}// end else if statement
		else if (tokens[index].getString().equals("replace")) {
			index++;
			ArrayList<String> replace = new ArrayList<String>();
			if(tokens[index].getType().equals("REGEX"))
			{
				replace.add(tokens[index].getString());
				index++;
			}// end if statement
			else {
				return false;
			}
			if (tokens[index].getString().equals("with")) {
				index++;
			}// end if statement
			else {
				return false;
			}//end else statement
			if(tokens[index].getType().equals("ASCII-STR"))
			{
				replace.add(tokens[index].getString());
				index++;
			}// end if statement
			else {
				return false;
			}
			if (tokens[index].getString().equals("in")) {
				index++;
				replace.add(tokens[index].getString());
			}// end if statement
			else {
				return false;
			}// end else statement
			replaces.add(replace);
			state = fileNames(index);
			if (!state) {
				return false;
			}
			if (tokens[index].getString().equals(";")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
		}// end else if statement
		else if (tokens[index].getString().equals("print")) {
			index++;
			if (tokens[index].getString().equals("(")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
			state = expList(index);
			if (!state) {
				return false;
			}
			if (tokens[index].getString().equals(")")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
			if (tokens[index].getString().equals(";")) {
				index++;
			}// end if statement
			else {
				return false;
			}// end else statement
		}// end else if statement
		else {
			return false;
		}
		return true;
	}// end statement method

	/**
	 * Leah
	 */
	public boolean statementListTail(int index)
	{
		boolean state;
		if(tokens[index].getType().equals("ID") || tokens[index].getString().equals("replace") || tokens[index].getString().equals("recursivereplace") || tokens[index].getString().equals("print")){
			state = statement(index);
			if(!state)
			{
				return false;
			}
			state = statementListTail(index);
		} else {
			return true;
		}
		return state;
	}//end statementListTail method

	/**
	 * Leah
	 */
	public boolean exp(int index) 
	{
		boolean state = true;
		if(tokens[index].getType().equals("ID"))
		{
			index++;
		} 
		else if (tokens[index].getString().equals("(")) 
		{
			index++;
			state = exp(index);
			if (tokens[index].getString().equals(")"))
			{
				index++;
			}
			else 
			{
				return false;
			}
		} 
		else if (tokens[index].getString().equals("find"))
		{
			state = term(index);
			if (!state) 
			{
				return false;
			}
			state = expTail(index);
		} 
		else 
		{
			return false;
		}
		return state;
	}// end exp methoddd

	public boolean maxfreqstring(int index) {
		return true;
	}// end maxfreqstring method

	/**
	 * Leah
	 */
	public boolean fileNames(int index) {
		boolean state;
		state = sourceFile(index);
		if (!state) {
			return false;
		}
		if (tokens[index].getString().equals("(")) {
			index++;
		} else {
			return false;
		}
		if (tokens[index].getString().equals(")")) {
			index++;
		} else {
			return false;
		}
		if (tokens[index].getString().equals("<!")) {
			index++;
		} else {
			return false;
		}
		state = destinationFile(index);
		return state;
	}// end fileNames method

	public boolean recursiveReplace(int index) {
		return true;
	}// end recursiveReplace method

	public boolean print(int index) {
		return true;
	}// end print method

	/**
	 * Leah
	 */
	public boolean expList(int index) {
		boolean state;
		state = exp(index);
		if (!state) {
			return false;
		}
		state = expListTail(index);
		return state;
	}// end expList method

	/**
	 * Kaitlin
	 */
	public boolean sourceFile(int index) 
	{
		if(tokens[index].getType().equals("ASCII-STR"))
		{
			index++;
		}// end if statement
		else {
			return false;
		}
		return true;
	}// end sourceFile method

	/**
	 * Kaitlin
	 */
	public boolean destinationFile(int index)
	{
		if(tokens[index].getType().equals("ASCII-STR"))
		{
			index++;
		}// end if statement
		else {
			return false;
		}
		return true;
	}// end destinationFile method

	/**
	 * Kaitlin
	 */
	public boolean expListTail(int index) {
		boolean state = true;
		if(tokens[index].getType().equals("ID")||tokens[index].getString().equals("(")||tokens[index].getString().equals("find"))
		{
			state = exp(index);
			if (!state) {
				return false;
			}
			state = expListTail(index);
		}// end else if statement
		else {
			return true;
		}
		return state;
	}// end expListTail method

	/**
	 * Kaitlin
	 */
	public boolean term(int index) {
		boolean state;
		if (tokens[index].getString().equals("find"))
		{
			index++;
		}// end if statement
		ArrayList<String> find = new ArrayList<String>();
		if(tokens[index].getType().equals("REGEX"))
		{
			find.add(tokens[index].getString());
			index++;
		}// end if statement
		else 
		{
			return false;
		}
		if (tokens[index].getString().equals("in"))
		{
			index++;
			find.add(tokens[index].getString());
		}// end if statement
		else 
		{
			return false;
		}// end else statement
		finds.add(find);
		state = fileName(index);
		if (!state)
		{
			return false;
		}
		return true;
	}// end term method

	/**
	 * Leah
	 */
	public boolean expTail(int index) {
		boolean state = true;
		if (tokens[index].getString().equals("diff")|| tokens[index].getString().equals("union")|| tokens[index].getString().equals("inters")) 
		{
			state = binOP(index);
			if (!state)
			{
				return false;
			}
			state = term(index);
			if (!state)
			{
				return false;
			}
			state = expTail(index);
		} 
		else 
		{
			return true;
		}
		return state;
	}// end expTail method

	/**
	 * Leah
	 */
	public boolean binOP(int index) {
		if (tokens[index].getString().equals("diff")|| tokens[index].getString().equals("union")|| tokens[index].getString().equals("inters")) {
			index++;
		} 
		else 
		{
			return false;
		}
		return true;
	}// end binOP method

	/**
	 * Kaitlin
	 */
	public boolean fileName(int index) 
	{
		if(tokens[index].getType().equals("ASCII-STR"))
		{
			index++;
		}// end if statement
		else 
		{
			return false;
		}
		return true;
	}//end fileName method
	
	public ArrayList<ArrayList<String>> getFindStatements(){return finds;}
	
	public ArrayList<ArrayList<String>> getReplaceStatements(){ return replaces;}
	
	public ArrayList<String> find(String regex,String filename){
		ArrayList<String> results = new ArrayList<String>();
		Token[] tokens = null;
		/**
		try {
		regexDFA = ScannerGenerator.dfaFromRegexString(regex);
			tokens = regexDFA.tokenize(new java.util.Scanner(new File(filename)));
		} catch (FileNotFoundException e) {
			System.out.println("");
			e.printStackTrace();
		}
		for(Token match:matches){if(token.getType().equals("MATCH")) results.add(token.getString());}
		*/
		return results;
	}
	
	public void replace(String regex,String replacement,String filename){
		ArrayList<String> results = new ArrayList<String>();
		Token[] matches = null;
		/**
		try {
			tokens = regexDFA.tokenize(new java.util.Scanner(new File(filename)));
		} catch (FileNotFoundException e) {
			System.out.println("");
			e.printStackTrace();
		}
		String edit = "";
		for(Token token:tokens){
			if(token.getType().equals("MATCH")){ token.getString() = replacement.substring(0,replacement.length); }
			edit.append(token);
		}
		//fileio
		PrintWriter out = new PrintWriter(filename);
		out.println(edit);
		out.close();
		*/
	}
	
}//end Interpreter class
